from django.shortcuts import render,redirect
from django.views.generic import View
from goods.models import GoodsCategory,Goods,GoodsSKU,IndexGoodsBanner,IndexCategoryGoodsBanner,IndexPromotionBanner
from django.core.cache import cache
from django_redis import get_redis_connection
from django.core.urlresolvers import reverse
from django.core.paginator import Paginator,EmptyPage
import json
# Create your views here.


class BaseCartView(View):
    """封装　　登录和未登录时购物车数据的读取　　　让在列表页　主页　详情页　都可以读取到购物车cart_num的数据"""
    def get_cart_num(self,request):

        cart_num = 0

        # 如果是登录用户，需要查询保存在redis 中的购物车数据
        if request.user.is_authenticated():

            # 创建连接到redis的对象
            redis_conn = get_redis_connection('default')

            # 调用hgetall()，查询hash对象还总所有数据，返回字典
            user_id = request.user.id
            cart_dict = redis_conn.hgetall('cart_%s' % user_id)

            # 遍历字典，读取商品数量，求和
            for val in cart_dict.values():
                cart_num += int(val)
        else:
            #用户访问商品模块页面时，我们读取在cookie中的购物车审计局
            cart_json = request.COOKIES.get('cart')
            #使用json模块，将cart_json 字符串，转字典
            if cart_json is not None:
                cart_dict = json.loads(cart_json)
            else:
                cart_dict = {}

             #遍历购物车字典
            for val in cart_dict.values():
                cart_num += val


        return cart_num


class ListView(BaseCartView):
    """商品分类　　列表页
    说明：
      展示某商品第几页的数据，然后再排序
    """
    def get(self,request,category_id,page_num):
        # 说明：展示     某商品         第几页    的数据，然后再排序

        # 读取排序规则 当用户不传入sort时，需要指定为默认排序规则
        sort = request.GET.get('sort','default')

        #查询用户要看的商品分类category对象
        try:
            category = GoodsCategory.objects.get(id = category_id)
        except GoodsCategory.DoesNotExist:
            return redirect(reverse('goods:index'))

        # 查询全部商品分类
        categorys = GoodsCategory.objects.all()

        # 查询新品推荐
        new_skus = GoodsSKU.objects.filter(category = category).order_by('-create_time')[:2]

        # 查询所有category关联的sku，并完成排序
        if sort == 'price':
            skus = GoodsSKU.objects.filter(category=category).order_by('price')
        elif sort == 'hot':
            skus = GoodsSKU.objects.filter(category=category).order_by('-sales')
        else:
            skus = GoodsSKU.objects.filter(category=category)
            #重置sort
            sort = 'default'

        # 实现分页 对skus分页，每页２个GoodsSKU模型对象
        paginator = Paginator(skus,2)
        # 获取用户要看的那页的数据
        page_num = int(page_num)
        # 要看的那页的数据：含有两个商品:page_skus = [GoodsSKU，GoodsSKU]
        try:
            page_skus = paginator.page(page_num)
        except EmptyPage:
            page_skus = paginator.page(1)

        # 先获取页码列表信息，再传给模板，不用在模板中获取
        page_list = paginator.page_range

        cart_num = self.get_cart_num(request)


        # 构造上下文
        context ={
            'category':category,
            'categorys':categorys,
            'new_skus':new_skus,
            'page_skus':page_skus, #只需要传入分页后的商品sku信息
            'page_list':page_list,
            'sort':sort,
            'cart_num':cart_num

        }
        # 渲染模板
        return render(request,'list.html',context)

class DetailView(BaseCartView):
    """详情"""
    def get(self,request,sku_id):
        """查询详情信息，渲染模板"""
        # 查询商品SKU信息
        try:
            sku = GoodsSKU.objects.get(id = sku_id)
        except GoodsSKU.DoesNotExist:
            return redirect(reverse('goods:index'))
        # 查询所有商品分类信息
        categorys = GoodsCategory.objects.all()
        # 查询商品详情信息 模板中可以查到

        # 查询商品评论信息
        # 从订单中获取评论信息　一个商品对应多个订单　
        sku_orders = sku.ordergoods_set.all().order_by('-create_time')[:30]
        if sku_orders:
            for sku_order in sku_orders:
                sku_order.ctime = sku_order.create_time.strftime('%Y-%m-%d %H:%M:%S')
                sku_order.username = sku_order.order.user.username
        else:
            sku_orders = []
        # 查询最新商品推荐
        new_skus = GoodsSKU.objects.filter(category = sku.category).order_by('-create_time')[:2]

        # 查询其他规格商品
        other_skus = sku.goods.goodssku_set.exclude(id = sku_id)

        # 如果已登录，查询购物车信息
        # 如果是登录用户，需要查询保存在redis 中的购物车数据
        cart_num = self.get_cart_num(request)
        if request.user.is_authenticated():

            # 创建连接到redis的对象
            redis_conn = get_redis_connection('default')

            # 调用hgetall()，查询hash对象还总所有数据，返回字典
            user_id = request.user.id


            # 先去重
            redis_conn.lrem("history_%s" %user_id,0,sku_id)
            # 记录用户浏览信息　增加sku_id
            redis_conn.lpush('history_%s' %user_id,sku_id)
            #最多存５个
            redis_conn.ltrim('history_%s' %user_id,0,4)




        context = {
            "categorys": categorys,
            "sku": sku,
            "sku_orders": sku_orders,
            "new_skus": new_skus,
            "other_skus": other_skus,
            'cart_num':cart_num
        }
        return render(request,'detail.html',context)

class IndexView(BaseCartView):
    """主页"""
    def get(self,request):
        """查询主页商品数据，并渲染"""
        # 先从缓存中读取数据，如果有就获取缓存数据，反之，就执行查询

        context = cache.get('index_page_data')

        if context is None:
            print('没有缓存数据查询数据库')
            #查询商品分类信息
            categorys = GoodsCategory.objects.all()

            # 查询图片轮播信息
            goods_banners = IndexGoodsBanner.objects.all().order_by('index')

            # 查询商品活动信息
            promotion_banners = IndexPromotionBanner.objects.all().order_by('index')

            # 查询商品分类列表展示信息
            for category in categorys:
                #遍历六种商品分类
                image_banners = IndexCategoryGoodsBanner.objects.filter(category=category,display_type=1)
                category.image_banners = image_banners

                title_banners = IndexCategoryGoodsBanner.objects.filter(category=category,display_type=0)
                category.title_banners = title_banners


            # 构造上下文
            context = {
                'categorys':categorys,
                'goods_banners':goods_banners,
                'promotion_banners':promotion_banners,

            }

            # 缓存context
            cache.set('index_page_data',context,3600)

        # 查询购物车信息
        cart_num = self.get_cart_num(request)


        # 补充购物车信息
        context.update(cart_num = cart_num)

        # 渲染页面
        return render(request,'index.html',context)




